﻿using MetroDataQuery.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MetroDataApi.Models
{
    public class Recent2Changes
    {
        public static List<recentChanges> AllChanges(int prjId, string startTime, string endTime)
        {
            try
            {
                using (var db = new MetroDataDataContext())
                {
                    var list = new List<recentChanges>();
                    var monitorLocations = from p in db.MonitorPointsDictionary
                                           where p.PrjId == prjId
                                           group p by new { p.Location, p.MonitorType } into g
                                           select g.Key;
                    foreach (var k in monitorLocations)
                    {
                        var changes = Recent2Changes.GetChanges(prjId, k.MonitorType, k.Location, startTime, endTime, "1");
                        if (changes.curValues.Count() > 0)
                        {
                            list.Add(changes);
                        }
                    }
                    return list;
                }
            }
            catch
            {
                return new List<recentChanges>();
            }
        }


        public static recentChanges GetChanges(int prjId, string monitorType, string location,
            string time1 = "", string time2 = "", string fuzzy = "0", bool isDesign = false)
        {
            try
            {
                var recentAllTimes = new List<string>();
                var times = new List<string>();
                if (time1.Length == 0)
                {
                    times = Recent2Changes.get2Times(prjId, location, monitorType, "", "");
                    recentAllTimes = MetroDataQuery.Utility.MonitorPointsQuery.GetMonitorDateList(prjId, monitorType,
                        location).ToList();
                }
                else
                {
                    times.Add(time1);
                    times.Add(time2);
                    //如果time1,time2是降序排列,下面的代码中,计算时要求*顺序*排列
                    if (DateTime.Parse(time1) > DateTime.Parse(time2))
                    {
                        times.Reverse();
                    }

                    if (fuzzy == "1")//模糊日期查询,用户只指定了前后时间段,需要查找具体测项日期
                    {
                        //根据起始时间,寻找最符合的最大和最小日期
                        times = Recent2Changes.GetActual2TimesByFuzzyTime(prjId, monitorType, location, times[0], times[1]);
                    }
                }

                var oTime = MonitorPointsQuery.GetOriginTime(prjId, monitorType, location);
                var names = PointsDictionaryQuery.GetPointNames(prjId, monitorType, location);
                if (names.Count == 0 || times.Count < 2 || oTime == "") new recentChanges();
                //查询变化量
                var lastCaculatedValues = QueryResults.GetResultsByDateTime(prjId,
                    monitorType, location, times[0], isDesign ? false : true, isDesign);
                var currentCaculatedValues = QueryResults.GetResultsByDateTime(prjId,
                    monitorType, location, times[1], isDesign ? false : true, isDesign);

                //对时间的一个特别处理,如果日期一致,那么就具体到时分
                var lastDate = DateTime.Parse(times[0]);
                var curDate = DateTime.Parse(times[1]);
                var lastTimeStr = ""; var curTimeStr = "";
                if (lastDate.Date == curDate.Date)
                {//日期一致
                    lastTimeStr = lastDate.ToString("yyyy-MM-dd HH:mm");
                    curTimeStr = curDate.ToString("yyyy-MM-dd HH:mm");
                }
                else
                {
                    lastTimeStr = lastDate.ToString("yyyy-MM-dd");
                    curTimeStr = curDate.ToString("yyyy-MM-dd");
                }

                var change = new recentChanges()
                {
                    lastValues = lastCaculatedValues,
                    lastTime = lastTimeStr,
                    curValues = currentCaculatedValues,
                    curTime = curTimeStr,
                    max = Math.Max(lastCaculatedValues.Where(p => !double.IsNaN(p.value)).Max(p => p.value),
                        currentCaculatedValues.Where(p => !double.IsNaN(p.value)).Max(p => p.value)),
                    min = Math.Min(lastCaculatedValues.Where(p => !double.IsNaN(p.value)).Min(p => p.value),
                        currentCaculatedValues.Where(p => !double.IsNaN(p.value)).Min(p => p.value)),
                    allTimes = recentAllTimes,
                    originTime = oTime,
                    pointsCount = names.Count,
                    title = location + monitorType
                };

                change.clear();
                //统计最大最小值
                change.summary();
                return change;
            }
            catch
            {
                return new recentChanges();
            }

        }


        public static recentChanges GetChangesIncludingUnReview(int prjId, string monitorType, string location, string dateStr = "")
        {
            var timeItems = Recent2Changes.Get2TimesIncludingUnReview(prjId, monitorType, location, dateStr);
            var lastTimeStr = timeItems[0].Date.ToString("yyyy-MM-dd HH:mm:ss");
            var curTimeStr = timeItems[1].Date.ToString("yyyy-MM-dd HH:mm:ss");
            var lastCaculatedValues = timeItems[0].IsReview ? QueryResults.GetReviewResultsByDateTime(prjId, monitorType, location, timeItems[0].Date)
                : QueryResults.GetResultsByDateTime(prjId, monitorType, location, lastTimeStr);
            var currentCaculatedValues = timeItems[1].IsReview ? QueryResults.GetReviewResultsByDateTime(prjId, monitorType, location, timeItems[1].Date)
                : QueryResults.GetResultsByDateTime(prjId, monitorType, location, curTimeStr);
            var oTime = MonitorPointsQuery.GetOriginTime(prjId, monitorType, location);

            var change = new recentChanges()
            {
                lastValues = lastCaculatedValues,
                lastTime = lastTimeStr,
                curValues = currentCaculatedValues,
                curTime = curTimeStr,
                max = Math.Max(lastCaculatedValues.Where(p => !double.IsNaN(p.value)).Max(p => p.value),
                    currentCaculatedValues.Where(p => !double.IsNaN(p.value)).Max(p => p.value)),
                min = Math.Min(lastCaculatedValues.Where(p => !double.IsNaN(p.value)).Min(p => p.value),
                    currentCaculatedValues.Where(p => !double.IsNaN(p.value)).Min(p => p.value)),
                originTime = oTime,
                pointsCount = 0,
                title = location + monitorType
            };

            change.clear();
            //统计最大最小值
            change.summary();
            return change;
        }

        public static List<string> get2Times(int prjId, string location, string monitorType, string startTime, string endTime)
        {
            var times = new List<string>();

            using (var db = new MetroDataDataContext())
            {
                if (startTime == "")
                {
                    times = MonitorPointsQuery.GetMonitorTimeList(prjId, monitorType, location, "", endTime, 2).Reverse().ToList();
                }
                else
                {
                    times = Recent2Changes.GetActual2TimesByFuzzyTime(prjId, monitorType, location, startTime, endTime);
                }
                if (times.Count == 1)
                {
                    times.Add(times[0]);
                }
                else if (times.Count == 0)
                {
                    return new List<string>();
                }
                return times;
            }
        }

        /// <summary>
        /// 返回包括未审核数据在内的,最近2次时间列表
        /// </summary>
        /// <param name="prjId"></param>
        /// <param name="location"></param>
        /// <param name="monitorType"></param>
        /// <returns></returns>
        public static List<UnReviewTimeItem> Get2TimesIncludingUnReview(int prjId, string monitorType, string location, string dateStr = "")
        {
            var timeList = Recent2Changes.get2Times(prjId, location, monitorType, "", "")
                        .Select(p => new UnReviewTimeItem() { Date = DateTime.Parse(p), IsReview = false });
            var unreviewtimeList = ReviewMonitorPointsQuery.GetMonitorTimeList(prjId, monitorType, location, dateStr)
                .Select(p => new UnReviewTimeItem() { Date = p.Value, IsReview = true }).Reverse();
            return timeList.Concat(unreviewtimeList).Reverse().Take(2).Reverse().ToList();
        }

        public class UnReviewTimeItem
        {
            public DateTime Date { get; set; }
            public bool IsReview { get; set; }
        }

        public static List<string> GetActual2TimesByFuzzyTime(int prjId, string monitorType, string location, string startTime, string endTime)
        {
            var times = new List<string>();
            using (var db = new MetroDataDataContext())
            {

                var timesAll = MonitorPointsQuery.GetMonitorTimeList(prjId, monitorType, location,
                    startTime, endTime).ToList();
                var minTime = timesAll.LastOrDefault();
                var maxTime = timesAll.FirstOrDefault();
                if (minTime == null || maxTime == null)
                {
                    //do nothing
                }
                else
                {
                    times.Add(minTime);
                    times.Add(maxTime);
                }
                return times;
            }
        }

    }


}